package cn.tedu.charging.cost.service;

import cn.tedu.charging.common.pojo.param.ProgressCostParam;
import cn.tedu.charging.common.pojo.po.ChargingCostRulePO;
import cn.tedu.charging.common.pojo.vo.ProgressCostVO;
import cn.tedu.charging.cost.repository.CostRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.Date;

/**
 * 省略接口 创建 直接实现类
 */
@Service
public class CostService {
    @Autowired
    private CostRepository costRepository;
    /**
     * redisTemplate底层序列化模式 RedisSerializer.java()
     * 导致在redis存储的string数据 不是数字 123->\X0\X1\X9123
     * 需要替换成RedisSerializer.string();
     */
    @Autowired
    private StringRedisTemplate redisTemplate;
    public ProgressCostVO calculateCost(ProgressCostParam param) {
        /**
         * 关于充电计价,根据时间节点 根据充电站 设备类型等不同条件因素 读取的规定结果
         */
        //1.拿到充电单价 到charging_cost_rule查询 计价规则 拿到单价
        //select * from charging_cost_rule where 站场id 枪类型 时间段
        //站场id=param.getStationId 枪类型=远程调用查询枪的详细数据.getType
        /**
         * 尖(上午,下午)8-12点 14-18
         * 峰 18-24点
         * 平 12-14点
         * 谷 0-8
         * start_time<=now()<end_time  [0,8) [8,12) [12,14) [14,18) [18,24)
         * 8点 12点 14点 18点 24点 0点
         */
        ChargingCostRulePO costRule=getCostRule(param.getStationId(),new Date());//拿到满足条件的计价规则
        //2.查询价格规则 可以根据参数充电度数 做结算 单次金额 poweeFee*param.getCapacity
        BigDecimal perFee=calculatePowerfee(param.getChargingCapacity(),costRule.getPowerFee());
        //3.计算历史叠加累计金额
        BigDecimal totalFee=accumulatePowerfee(perFee,param.getOrderNo());
        //封装vo返回
        ProgressCostVO vo=new ProgressCostVO();
        vo.setPowerFee(costRule.getPowerFee().doubleValue());//一度电 单价
        vo.setTotalCost(totalFee.doubleValue());
        return vo;
    }

    private BigDecimal accumulatePowerfee(BigDecimal perFee,String orderNo) {
        //单次计算金额是5元 累计金额 需要一个历史累计金额 上次计算总价
        //使用redis客户端的计步器逻辑 累加
        //1.准备每张订单 累计金额的key值
        String orderCostTotalKey="order:cost:total:"+orderNo;
        //2.将perFee单次金额转化成int 累加但是redis客户端template已经实现了这个转化
        //incrby key perFee
        Double increment = redisTemplate.boundValueOps(orderCostTotalKey).increment(perFee.doubleValue());
        return new BigDecimal(increment);
    }

    private BigDecimal calculatePowerfee(Double chargingCapacity, BigDecimal powerFee) {
        //乘法执行 api代码 精度 2位 四舍五入78.975~78.98 78.974~ 78.97
        //所有计算单价的数据 都转化成bigDecimal
        BigDecimal perFee = new BigDecimal(chargingCapacity).multiply(powerFee);//拿到单次价格
        return perFee.setScale(2,BigDecimal.ROUND_HALF_UP);
    }

    private ChargingCostRulePO getCostRule(Integer stationId, Date now) {
        return costRepository.getCostRule(stationId,now);
    }
}
